/**
 * 
 */
package recognition.input;

import handwritten.gesture.HandInputManager;
import handwritten.gesture.MultiGesture;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.xml.bind.annotation.XmlType;


/**
 * @author Louis
 *
 */

@XmlType (
	    name = "##default", 
	    propOrder = {""}, 
	    namespace = "##default" 
	    //factoryClass = DEFAULT.class, 
	    //factoryMethod = ""
	)


public class CellInput extends Input<double[]> {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -2005855306311620350L;
	public static final int INPUT_CELL_SIZE_X = 10;
	public static final int INPUT_CELL_SIZE_Y = 10;
	
	public CellInput(){}

	protected CellInput(MultiGesture gesture) {
		super(gesture);
		
		/*for(int y = 0; y<INPUT_CELL_SIZE_Y; y++){
			for(int x = 0; x<INPUT_CELL_SIZE_X; x++){
				System.out.print(getInput()[y*INPUT_CELL_SIZE_X+x]+" ");
			}
			System.out.println();
		}*/
	}

	/* (non-Javadoc)
	 * @see textRecognition.input.Input#fillInput(textRecognition.gesture.Gesture)
	 */
	@Override
	protected void fillInput(MultiGesture gesture) {
		
		
		int cell[][]=new int[60][60];
		
		gesture.fillPath(cell);
		
		/*for(int y = 0; y<60; y++){
			for(int x = 0; x<60; x++){
				System.out.print(cell[x][y]+" ");
			}
			System.out.println();
		}*/
		
		cell = hCentering(cell);
		
		double[][] dist = distanceGrid(cell);
		
		int xPixelSize = cell.length/INPUT_CELL_SIZE_X;
		int yPixelSize = cell[0].length/INPUT_CELL_SIZE_Y;
		
		float min = Float.MAX_VALUE;
		float max = Float.MIN_VALUE;
		float val;
		
		for(int y = 0; y<INPUT_CELL_SIZE_Y; y++){
			for(int x = 0; x<INPUT_CELL_SIZE_X; x++){
				val = inputValue(x, y, xPixelSize, yPixelSize, dist);
				setInputAt(y*INPUT_CELL_SIZE_X+x, val);
				if(val < min)
					min = val;
				if(val > max)
					max = val;
			}
		}
		
		for(int i = 0; i< getInputSize(); i++)
			setInputAt(i, (getInput()[i]-min)/(max-min));
		
		/*try {
		    BufferedImage bi = new BufferedImage(INPUT_CELL_SIZE_X*20,INPUT_CELL_SIZE_Y*20,BufferedImage.TYPE_INT_RGB);
		    
		    for(int y = 0; y<INPUT_CELL_SIZE_Y; y++){
				for(int x = 0; x<INPUT_CELL_SIZE_X; x++){
					int rgb = new Color(
							1-(float)getInput()[y*INPUT_CELL_SIZE_X+x],
							0,(float)getInput()[y*INPUT_CELL_SIZE_X+x]).getRGB();
					for(int i = 0; i<20; i++)
						for(int j = 0; j<20; j++)
							bi.setRGB(x*20+i, y*20+j, rgb);

				}
			}
		    
		    ImageIO.write(bi, "png", new File("outputs/"+System.currentTimeMillis()+".png"));
		} catch (IOException e) {}*/
		
	}
	
	private double[][] distanceGrid(int[][] cell){
		ArrayList<int[]> pixOn = new ArrayList<int[]>();
		double[][] distances = new double[cell.length][cell[0].length];
		for(int x = 0; x<cell.length; x++){
			for(int y = 0; y<cell[0].length; y++){
				if(cell[x][y] > 0)
					pixOn.add(new int[]{x,y});
			}
		}
		double dist;
		for(int x = 0; x<cell.length; x++){
			for(int y = 0; y<cell[0].length; y++){
				distances[x][y] = Double.MAX_VALUE;
				for(int[] pix : pixOn){
					dist = Math.sqrt((x-pix[0])*(x-pix[0])+(y-pix[1])*(y-pix[1]));
					if(dist < distances[x][y])
						distances[x][y] = dist;
				}
			}
		}
		
		return distances;
	}
	
	public void setInputAt(int index,double value){
		getInput()[index]=value;
	}
	
	private int[][] hCentering(int[][] cell){
		int left  = emptyCol(cell,true);
		int right = emptyCol(cell,false);
			
		if(Math.abs(left-right) < 2)
			return cell;
		
		int[][] nCell = new int[cell.length][cell[0].length];
		
		
		int delta = (left+right)/2;
		int index;
		for(int x = delta; x<cell.length; x++){
			index = x+(left-delta);
			if(index >= 0 && index < cell.length){
				for(int y = 0; y<cell[0].length; y++){
					nCell[x][y] = cell[index][y];
				}
			}

		}
		
		return nCell;
	}
	
	private int emptyCol(int[][] cell, boolean left){
		
		int incr = left?1:-1;
		int start = left?0:(cell.length-1);
		
		int empty = 0;
		
		int sum = 0;
		
		
		for(int x = start; x != incr*(cell.length-start) && sum == 0; x+=incr){
			for(int y = 0; y<cell[0].length; y++)
				sum += cell[x][y];
			if(sum == 0)
				empty++;
		}
		
		return empty;
	}
	
	private float inputValue(int x, int y, int xPixelSize, int yPixelSize, double[][] cell){
		float value = 0;
		
		for(int pX = 0; pX < xPixelSize; pX++){
			for(int pY = 0; pY < yPixelSize; pY++){
				value+=cell[x*xPixelSize+pX][y*yPixelSize+pY];
			}
		}
		
		return value/(xPixelSize*yPixelSize);
	}

	protected int getInputSize() {
		return INPUT_CELL_SIZE_X*INPUT_CELL_SIZE_Y;
	}

	/* (non-Javadoc)
	 * @see recognition.input.Input#createInput()
	 */
	@Override
	public CellInput createInput(MultiGesture gesture) {
		return new CellInput(gesture);
	}

	/* (non-Javadoc)
	 * @see recognition.input.Input#createInput()
	 */
	@Override
	protected double[] createInput() {
		return new double[getInputSize()];
	}

}
